#include <napi/native_api.h>
// #include <sys/system_properties.h>
#include "helpers/general.h"
#include "helpers/resource.h"
#include "refs.h"
#include <cstdlib>
#include <string>

namespace ohos_rive {
extern std::unordered_map<std::string, napi_ref> g_classRegistry;

napi_value GetClass(napi_env env, const char *name)
{
    if (!name) {
        return nullptr;
    }

    auto it = g_classRegistry.find(std::string(name));
    if (it != g_classRegistry.end()) {
        napi_value clazz;
        napi_status status = napi_get_reference_value(env, it->second, &clazz);
        if (status == napi_ok) {
            return clazz;
        }
    }
    return nullptr;
}

napi_value GetMethodId(napi_env env, napi_value clazz, const char *name)
{
    // 获取构造函数的原型对象
    napi_value prototype;
    napi_status status = napi_get_named_property(env, clazz, "prototype", &prototype);
    if (status != napi_ok) {
        LOGE("Failed to get prototype for method: %{public}s", name);
        return nullptr;
    }

    // 从原型中获取方法
    napi_value method;
    status = napi_get_named_property(env, prototype, name, &method);
    if (status != napi_ok) {
        LOGE("Method not found in prototype: %{public}s", name);
        return nullptr;
    }
    // 验证获取的是函数
    napi_valuetype value_type;
    status = napi_typeof(env, method, &value_type);
    if (status != napi_ok || value_type != napi_function) {
        LOGE("Property %{public}s is not a function, type: %{public}d", name, value_type);
        return nullptr;
    }
    LOGI("Get method OK: %{public}s", name);
    return method;
}

napi_value GetStaticMethodId(napi_env env, napi_value clazz, const char *name)
{
    napi_status status;

    // 直接从类对象获取静态方法
    napi_value method;
    status = napi_get_named_property(env, clazz, name, &method);
    if (status != napi_ok) {
        LOGE("Failed to retrieve static method");
        return nullptr;
    }

    // 类型验证
    napi_valuetype valueType;
    status = napi_typeof(env, method, &valueType);
    if (status != napi_ok || valueType != napi_function) {
        LOGE("Static property is not a function");
        return nullptr;
    }
    LOGI("Get static method OK: %{public}s", name);
    return method;
}

napi_value GetStaticFieldId(napi_env env, napi_value clazz, const char *name)
{
    napi_value field;
    napi_status status = napi_get_named_property(env, clazz, name, &field);

    if (status != napi_ok) {
        LOGE("Failed to get static field: %{public}s", name);
        return nullptr;
    }

    return field;
}

napi_value GetFieldId(napi_env env, napi_value clazz, const char *name)
{
    // 获取构造函数的原型对象
    napi_value prototype;
    napi_status status = napi_get_prototype(env, clazz, &prototype);
    if (status != napi_ok) {
        LOGE("Failed to get prototype for field: %{public}s", name);
        return nullptr;
    }

    // 从原型中获取字段
    napi_value field;
    status = napi_get_named_property(env, prototype, name, &field);
    if (status != napi_ok) {
        LOGE("Field not found in prototype: %{public}s", name);
        return nullptr;
    }
    return field;
}

napi_status ThrowRiveException(napi_env env, const char *message)
{
    return napi_throw_error(env, "RIVE_ERROR", message);
}

napi_status ThrowMalformedFileException(napi_env env, const char *message)
{
    return napi_throw_error(env, "MALFORMED_FILE", message);
}

napi_status ThrowUnsupportedRuntimeVersionException(napi_env env, const char *message)
{
    return napi_throw_error(env, "UNSUPPORTED_VERSION", message);
}

napi_value GetLoopClass(napi_env env)
{
    return GetClass(env, "Loop");
}

napi_value GetNoneLoopField(napi_env env)
{
    return GetStaticFieldId(env, GetLoopClass(env), "NONE");
}
napi_value GetOneShotLoopField(napi_env env)
{
    return GetStaticFieldId(env, GetLoopClass(env), "ONESHOT");
}
napi_value GetLoopLoopField(napi_env env)
{
    return GetStaticFieldId(env, GetLoopClass(env), "LOOP");
}
napi_value GetPingPongLoopField(napi_env env)
{
    return GetStaticFieldId(env, GetLoopClass(env), "PINGPONG");
}

napi_value GetAdvanceResultClass(napi_env env)
{
    return GetClass(env, "AdvanceResult");
}

napi_value GetAdvanceResultAdvancedField(napi_env env)
{
    return GetStaticFieldId(env, GetAdvanceResultClass(env), "ADVANCED");
}

napi_value GetAdvanceResultOneShotField(napi_env env)
{
    return GetStaticFieldId(env, GetAdvanceResultClass(env), "ONESHOT");
}

napi_value GetAdvanceResultLoopField(napi_env env)
{
    return GetStaticFieldId(env, GetAdvanceResultClass(env), "LOOP");
}

napi_value GetAdvanceResultPingPongField(napi_env env)
{
    return GetStaticFieldId(env, GetAdvanceResultClass(env), "PINGPONG");
}

napi_value GetAdvanceResultNoneField(napi_env env)
{
    return GetStaticFieldId(env, GetAdvanceResultClass(env), "NONE");
}

napi_value GetRiveEventReportClass(napi_env env)
{
    return GetClass(env, "RiveEventReport");
}

napi_value GetRiveEventReportConstructorId(napi_env env)
{
    return GetMethodId(env, GetRiveEventReportClass(env), "constructor");
}

static const char *AABBFieldNames[] = {"left", "top", "right", "bottom"};

rive::AABB RectFToAABB(napi_env env, napi_value rectf)
{
    float values[4];

    for (int i = 0; i < 4; ++i) {
        napi_value property;
        napi_get_named_property(env, rectf, AABBFieldNames[i], &property);

        double value;
        napi_get_value_double(env, property, &value);
        values[i] = static_cast<float>(value);
    }

    return {values[0], values[1], values[2], values[3]};
}

void AABBToRectF(napi_env env, const rive::AABB &aabb, napi_value rectf)
{
    const float values[4] = {aabb.left(), aabb.top(), aabb.right(), aabb.bottom()};

    for (int i = 0; i < 4; ++i) {
        napi_value value;
        napi_create_double(env, values[i], &value);
        napi_set_named_property(env, rectf, AABBFieldNames[i], value);
    }
}
} // namespace ohos_rive
